import wx
import wx.lib.masked
import glob
import os
from Setting import Setting

import datetime
import SyncManager

class DialogAddItem(wx.Dialog):

    WISHLIST_MODE = 1
    TODO_MODE = 2

    choice_list = ('1','2','3','4','5')
    
    text_items = ('title','start','end','type','priority','where','description')
    def __init__(self, retl, flag, orgs=[], title=None):
        import DataManager 
        wx.Dialog.__init__(self, None, -1, "New", size=(400,450),
                           style=wx.DEFAULT_DIALOG_STYLE|
                           wx.THICK_FRAME|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)

        assert(type(retl) == list)
        #why do I need this? because I need to fill this in member function
        self.par = retl
        sizer = wx.GridBagSizer()

        #font
        font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
        font.SetPointSize(12)
        self.SetFont(font)

        self.title = wx.TextCtrl(self)
        self.start_d = wx.DatePickerCtrl(self, size=wx.Size(200, 30),
              style=wx.DP_DROPDOWN | wx.DP_ALLOWNONE | wx.DP_SHOWCENTURY)
        self.start_t = wx.lib.masked.TimeCtrl(self, displaySeconds = False, fmt24hr = True)
        self.end_d = wx.DatePickerCtrl(self, size=wx.Size(200, 30),
              style=wx.DP_DROPDOWN | wx.DP_ALLOWNONE | wx.DP_SHOWCENTURY)
        self.end_t = wx.lib.masked.TimeCtrl(self, displaySeconds = False, fmt24hr = True)

        #things are a little bit complicated with types
        self.thelist = DataManager.DataManager.types.data
        tmp = self.thelist.keys()
        self.type = wx.ComboBox(self, choices=tmp,
                                style=wx.CB_DROPDOWN|wx.CB_READONLY, size=wx.Size(100,30))
        self.subtype = wx.ComboBox(self, choices=[],
                                style=wx.CB_DROPDOWN|wx.CB_READONLY, size=wx.Size(100,30))
        self.type.Bind(wx.EVT_TEXT, self.prime_change)
        
        self.where = wx.TextCtrl(self) 
        self.rmd = wx.CheckBox(self, label='reminder')
        self.prio = wx.ComboBox(self, choices=self.choice_list,
                                style=wx.CB_DROPDOWN|wx.CB_READONLY, size=wx.Size(100,30))
        self.desc = wx.TextCtrl(self, size=(300,150), style=wx.TE_MULTILINE|wx.TE_AUTO_URL)
        b = wx.Button(self, -1, "OK")
        c = wx.Button(self, -1, "Cancel")

        self.do_init(orgs, title)

        sizer.Add(wx.StaticText(self, label = self.text_items[0]), (1,1))
        sizer.Add(self.title, (1,2))

        sizer.Add(wx.StaticText(self, label = self.text_items[1]), (2,1))
        sizer.Add(self.start_d, (2,2), span=(1,2))
        sizer.Add(self.start_t, (2,4))
        sizer.Add(wx.StaticText(self, label = self.text_items[2]), (3,1))
        sizer.Add(self.end_d, (3,2), span=(1,2))
        sizer.Add(self.end_t, (3,4))

        sizer.Add(wx.StaticText(self, label = self.text_items[3]), (5,1))
        sizer.Add(self.type, (5,2))
        sizer.Add(self.subtype, (5,3))
        sizer.Add(wx.StaticText(self, label = self.text_items[4]), (6,1))
        sizer.Add(self.prio, (6,2))
        sizer.Add(self.rmd, (6,3))

        sizer.Add(wx.StaticText(self, label = self.text_items[5]), (7,1))
        sizer.Add(self.where, (7,2))

        #span is really a strange parameter
        sizer.Add(wx.StaticText(self, label = self.text_items[6]), (8,1))
        sizer.Add(self.desc, (9,1), span=(2,3), flag=wx.EXPAND)
        sizer.Add(b, (11,1))
        sizer.Add(c, (11,2))
        self.SetSizer(sizer)

        b.Bind(wx.EVT_BUTTON, self.on_ok)
        c.Bind(wx.EVT_BUTTON, self.on_cancel)
        b.SetFocus()

    def prime_change(self, evt):
        self.subtype.Clear()
        for i in self.thelist[self.type.GetValue()]:
            self.subtype.Append(i)
        
    def on_ok(self, evt):
        #NOTE: self.par, the list should not be deleted or replaced, for
        #otherwise the caller won't see any results returned. It works
        #like a pointer to memory
        self.par.append(self.title.GetValue())
        #start
        ret = self.start_d.GetValue()
        y = ret.GetCurrentYear()
        m = ret.GetMonth()+1
        d = ret.GetDay()
        hm = self.start_t.GetValue().split(':')
        hour = int(hm[0])
        minu = int(hm[1])
        start = datetime.datetime(y,m,d,hour,minu)
        self.par.append(start)
        #end
        ret = self.end_d.GetValue()
        y = ret.GetCurrentYear()
        #those who developed DatePickerCtrl must be a weirdo
        m = ret.GetMonth()+1
        d = ret.GetDay()
        hm = self.end_t.GetValue().split(':')
        hour = int(hm[0])
        minu = int(hm[1])
        end = datetime.datetime(y,m,d,hour,minu)
        self.par.append(end)
        
        self.par.append(self.where.GetValue())
        self.par.append(self.desc.GetValue())
        self.par.append(self.type.GetValue()+'_'+self.subtype.GetValue())
        #repetition, we do not deal with this
        self.par.append(0)
        self.par.append(int(self.rmd.GetValue()))
        self.par.append(int(self.prio.GetValue()))
        self.EndModal(0)

    def on_cancel(self, evt):
        self.EndModal(-1)
        
    def do_init(self, orgs, title):
            #title
        self.title.SetValue(orgs[0])
            #start day
        date = wx.DateTimeFromDMY(int(orgs[1].day), int(orgs[1].month)-1, int(orgs[1].year))
        self.start_d.SetValue(date)
            #start time
        t = "%d:%d"%(orgs[1].hour, orgs[1].minute)
        self.start_t.SetValue(t)
            #end day
        date = wx.DateTimeFromDMY(int(orgs[2].day), int(orgs[2].month)-1, int(orgs[2].year))
        self.end_d.SetValue(date)
            #end time
        t = "%d:%d"%(orgs[2].hour, orgs[2].minute)
        self.end_t.SetValue(t)
        self.where.SetValue(orgs[3])
        self.desc.SetValue(orgs[4])

        #split this string
        prime_t, sub_t = orgs[5].split('_', 1)
        self.type.SetValue(prime_t)
        self.subtype.SetValue(sub_t)
        self.rmd.SetValue(orgs[7])
        #prio need to be converted from int to string
        self.prio.SetValue(str(orgs[8]))

            
class DialogLogin(wx.Dialog):
    """
    this is the login dialog
    """
    def __init__(self, ret):
        wx.Dialog.__init__(self, None, -1, "Login", size=(450,200),
                           style=wx.DEFAULT_DIALOG_STYLE|
                           wx.THICK_FRAME|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
        sizer = wx.GridBagSizer()

        font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
        font.SetPointSize(12)
        self.SetFont(font)

        
        self.un_s = wx.StaticText(self, label='user name')        
        self.un = wx.TextCtrl(self, size=(200,40))
        self.un.SetValue(Setting.get('username'))
        
        self.pw_s = wx.StaticText(self, label='password')        
        self.pw = wx.TextCtrl(self, size=(200,40), style=wx.TE_PASSWORD)
        self.pw.SetValue(Setting.get('password'))

        self.rmbc = wx.CheckBox(self, label='save password')
        self.rmbc.SetValue(Setting.get('save_password'))
        
        self.btn_ok = wx.Button(self, -1, 'Login')
        self.btn_cancel = wx.Button(self, -1, 'Cancel')
        self.btn_register = wx.Button(self, -1, 'Register')

        self.Bind(wx.EVT_BUTTON, self.on_ok, self.btn_ok)
        self.Bind(wx.EVT_BUTTON, self.on_cancel, self.btn_cancel)
        self.Bind(wx.EVT_BUTTON, self.on_register, self.btn_register)

        self.ret = ret
        
        sizer.Add(self.un_s, (1,0))
        sizer.Add(self.un, (1,1))
        sizer.Add(self.pw_s, (2,0))
        sizer.Add(self.pw, (2,1))
        sizer.Add(self.rmbc, (3,0))
        sizer.Add(self.btn_ok, (4,0))
        sizer.Add(self.btn_cancel, (4,1))
        sizer.Add(self.btn_register, (4,2))
        self.SetSizer(sizer)

    def on_ok(self, evt):
        #self.deal_setting()
        self.ret.append(self.rmbc.GetValue())
        self.ret.append(self.un.GetValue())
        self.ret.append(self.pw.GetValue())
        self.EndModal(0)

    def on_cancel(self, evt):
        self.EndModal(-1)

    def on_register(self, evt):
        d = DialogRegister([])
        r = d.ShowModal()
        d.Destroy()

    def deal_setting(self):
        if self.rmbc.GetValue():
            Setting.set('username', self.un.GetValue())
            Setting.set('password', self.pw.GetValue())

        #always save this
        Setting.set('save_password', self.rmbc.GetValue())
        Setting.save()

class DialogRegister(wx.Dialog):
    """
    this is the login dialog
    """
    def __init__(self, ret):
        wx.Dialog.__init__(self, None, -1, "Register", size=(400,200),
                           style=wx.DEFAULT_DIALOG_STYLE|
                           wx.THICK_FRAME|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
        sizer = wx.GridBagSizer()

        font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
        font.SetPointSize(12)
        self.SetFont(font)

        
        self.un_s = wx.StaticText(self, label='user name')        
        self.un = wx.TextCtrl(self, size=(200,30))
        
        self.pw_s = wx.StaticText(self, label='password')        
        self.pw = wx.TextCtrl(self, size=(200,30), style=wx.TE_PASSWORD)

        self.btn_ok = wx.Button(self, -1, 'Register')
        self.btn_cancel = wx.Button(self, -1, 'Cancel')

        self.Bind(wx.EVT_BUTTON, self.on_ok, self.btn_ok)
        self.Bind(wx.EVT_BUTTON, self.on_cancel, self.btn_cancel)
        self.st = wx.StaticText(self, label='') 

        self.ret = ret
        ret[0:1] = ['', '']
        
        sizer.Add(self.un_s, (1,0))
        sizer.Add(self.un, (1,1))
        sizer.Add(self.pw_s, (2,0))
        sizer.Add(self.pw, (2,1))
        sizer.Add(self.btn_ok, (4,0))
        sizer.Add(self.btn_cancel, (4,1))
        sizer.Add(self.st, (5,0))
        self.SetSizer(sizer)

        self.rm = SyncManager.RegisterManager()

    def on_ok(self, evt):
        username = self.un.GetValue()
        if len(username) < 2:
            self.st.SetLabel('username too short')
            return
        password = self.pw.GetValue()
        if len(password) < 6:
            self.st.SetLabel('password too short')
            return
        self.st.SetLabel('trying to register')
        r = 0
        
        try:
            r = self.rm.do_register(username, password)
        except:
            r = -1
            plus = 'exception'
            
        if r == 0:
            self.EndModal(0)
        else:
            if r == 11:
                plus = 'username already exist'
            elif r == 13:
                plus = 'username >= 2'
            elif r == 14:
                plus = 'password >= 6'
            else:
                print('r == %d'%(r))
                plus = ''
                self.st.SetLabel('register failed: '+ plus)
        return
        

    def on_cancel(self, evt):
        self.EndModal(-1)

class DialogChooseDB(wx.Dialog):
    """
    this dialog is used to choose a db file
    """
    def __init__(self, retl):
        wx.Dialog.__init__(self, None, -1, "Choose a database", size=(430,330),
                           style=wx.DEFAULT_DIALOG_STYLE|
                           wx.THICK_FRAME|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
        sizer = wx.GridBagSizer()

        db_list = glob.glob('*.db')
        if len(db_list) == 0:
            db_list.append('default.db')
        self.list = l = wx.ListCtrl(self, style = wx.LC_REPORT, size=(300,300))
        l.InsertColumn(0, 'name', width=300)
        btn_ok = wx.Button(self, -1, 'ok')
        btn_new = wx.Button(self, -1, 'new')
        btn_delete = wx.Button(self, -1, 'delete')
        btn_cancel = wx.Button(self, -1, 'cancel')
        for i, j in enumerate(db_list):
            l.InsertStringItem(i+1, j.split('.', 1)[0])
        sizer.Add(l, (0,0), span=(10,1))
        sizer.Add(btn_ok, (1,3))
        sizer.Add(btn_new, (3,3))
        sizer.Add(btn_delete, (5,3))
        sizer.Add(btn_cancel, (7,3))
        
        self.SetSizer(sizer)

        self.Bind(wx.EVT_BUTTON, self.on_ok, btn_ok)
        self.Bind(wx.EVT_BUTTON, self.on_new, btn_new)
        self.Bind(wx.EVT_BUTTON, self.on_delete, btn_delete)
        self.Bind(wx.EVT_BUTTON, self.on_cancel, btn_cancel)

        #set focus to save time
        btn_ok.SetFocus()

        self.retl = retl

    def on_ok(self, evt):
        idx = self.list.GetFirstSelected()
        if idx == -1:
            idx = 0
        #this shows that listctrl is really a very unfriendly wiget
        self.retl.append(self.list.GetItem(idx,0).GetText()+'.db')
        self.EndModal(0)

    def on_new(self, evt):
        #use another dialog to get the name of the new db
        dlg = wx.TextEntryDialog(self, 'enter new database name', 'new database')
        if dlg.ShowModal() == wx.ID_OK:
            self.retl.append(dlg.GetValue()+'.db')
            self.EndModal(0)
        return

    def on_delete(self, evt):
        idx = self.list.GetFirstSelected()
        if idx == -1:
            return
        #this shows that listctrl is really a very unfriendly wiget
        name = self.list.GetItem(idx,0).GetText() + '.db'
        try:
            os.remove(name)
        except:
            pass
        self.list.DeleteItem(idx)
            

    def on_cancel(self, evt):
        self.EndModal(-1)

class DialogSync(wx.ProgressDialog):
    def __init__(self):
        wx.ProgressDialog.__init__(self, "Synchronizing", 'preparing...')
        self.counter = 0
        self.sync = SyncManager.SyncManager()
        self.sync.start()
        #self.sync.run()
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.scallback, self.timer)
        self.timer.Start(500)
        
    def scallback(self, evt):
        if self.sync.isAlive() == False:
            self.timer.Stop()
            self.EndModal(-self.sync.level)
            return
        if self.sync.level == 1:
            self.Pulse('login...')
        elif self.sync.level == 2:
            self.Pulse('pull data...')
        elif self.sync.level == 3:
            self.Pulse('merge data...')
        elif self.sync.level == 4:
            self.Pulse('push data...')
        elif self.sync.level == 5:
            self.Pulse('cleanup...')
        else:
            self.Pulse('....')

if __name__ == "__main__":
    import datetime
    import DataManager
    DataManager.DataManager.init('default.db')
    app = wx.App()
    retl = []
    d = DialogAddItem(retl, DialogAddItem.WISHLIST_MODE,
                      ['', datetime.datetime.now(), datetime.datetime.now(), '', '', '', 0, 0, 1])
    #d = DialogLogin(retl)
    #d = DialogChooseDB(retl)
    #d = DialogSync()
    retv = d.ShowModal()
    d.Destroy()
    print(retl)
